﻿Imports System
Imports System.Diagnostics
Imports System.Reflection
Imports System.Security.Principal
Imports System.Threading
Imports System.Workflow.Runtime

Namespace System.Workflow.Activities
    <Serializable> _
    Friend NotInheritable Class WorkflowMessageEventHandler
        ' Methods
        Friend Sub New(ByVal proxiedType As Type, ByVal eventInfo As EventInfo, ByVal runtime As WorkflowRuntime)
            Me.proxiedType = proxiedType
            Me.eventName = eventInfo.Name
            Me.eventHandlerType = eventInfo.EventHandlerType
            Me.runtime = runtime
        End Sub

        Public Sub EventHandler(ByVal sender As Object, ByVal eventArgs As ExternalDataEventArgs)
            If (eventArgs Is Nothing) Then
                Throw New ArgumentNullException("eventArgs")
            End If
            Try 
                Dim objArray As Object() = New Object() { sender, eventArgs }
                Dim workflow As WorkflowInstance = Me.runtime.GetWorkflow(eventArgs.InstanceId)
                Dim key As EventQueueName = Me.GetKey(objArray)
                Dim name As String = Nothing
                If (eventArgs.Identity Is Nothing) Then
                    Dim identity As IIdentity = Thread.CurrentPrincipal.Identity
                    Dim identity2 As WindowsIdentity = [TryCast](identity,WindowsIdentity)
                    If ((Not identity2 Is Nothing) AndAlso (Not identity2.User Is Nothing)) Then
                        name = identity2.User.Translate(GetType(NTAccount)).ToString
                    ElseIf (Not identity Is Nothing) Then
                        name = identity.Name
                    End If
                    eventArgs.Identity = name
                Else
                    name = eventArgs.Identity
                End If
                Dim workHandler As IPendingWork = eventArgs.WorkHandler
                Dim workItem As Object = eventArgs.WorkItem
                eventArgs.WorkHandler = Nothing
                eventArgs.WorkItem = Nothing
                Dim item As New MethodMessage(Me.proxiedType, Me.eventName, objArray, name)
                WorkflowActivityTrace.Activity.TraceEvent(TraceEventType.Information, 0, "Firing event {0} for instance {1}", New Object() { Me.eventName, eventArgs.InstanceId })
                If eventArgs.WaitForIdle Then
                    workflow.EnqueueItemOnIdle(key, item, workHandler, workItem)
                Else
                    workflow.EnqueueItem(key, item, workHandler, workItem)
                End If
            Catch exception As Exception
                If ExternalDataExchangeService.IsIrrecoverableException(exception) Then
                    Throw
                End If
                Throw New EventDeliveryFailedException(SR.GetString("Error_EventDeliveryFailedException", New Object() { Me.proxiedType, Me.eventName, eventArgs.InstanceId }), exception)
            End Try
        End Sub

        Private Function GetKey(ByVal eventArgs As Object()) As EventQueueName
            Dim provideInitializerTokens As Boolean = CorrelationResolver.IsInitializingMember(Me.proxiedType, Me.eventName, eventArgs)
            Return New EventQueueName(Me.proxiedType, Me.eventName, CorrelationResolver.ResolveCorrelationValues(Me.proxiedType, Me.eventName, eventArgs, provideInitializerTokens))
        End Function


        ' Properties
        Friend ReadOnly Property [Delegate] As Delegate
            Get
                Dim parameters As ParameterInfo() = Me.eventHandlerType.GetMethod("Invoke").GetParameters
                Dim flag As Boolean = False
                If ((parameters.Length = 2) AndAlso (parameters(1).ParameterType.IsSubclassOf(GetType(ExternalDataEventArgs)) OrElse (parameters(1).ParameterType Is GetType(ExternalDataEventArgs)))) Then
                    flag = True
                End If
                If flag Then
                    Dim method As MethodInfo = GetType(WorkflowMessageEventHandler).GetMethod("EventHandler")
                    Return DirectCast(Activator.CreateInstance(Me.eventHandlerType, New Object() { Me, method.MethodHandle.GetFunctionPointer }), Delegate)
                End If
                Return Nothing
            End Get
        End Property


        ' Fields
        <NonSerialized> _
        Private eventHandlerType As Type
        Private eventName As String
        Private proxiedType As Type
        <NonSerialized> _
        Private runtime As WorkflowRuntime
    End Class
End Namespace

